#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/time.h>

int parse_mac(const char* s, uint8_t* mac)
{
    int vals[6];
    if (sscanf(s, "%x:%x:%x:%x:%x:%x", &vals[0],&vals[1],&vals[2],&vals[3],&vals[4],&vals[5]) != 6) {
        return -1;
    }
    for (int i = 0;i < 6;i++) {
        mac[i] = (uint8_t)vals[i];
    }
    return 0;
}

int tun_alloc(char *dev) 
{
    struct ifreq ifr;
    int fd = open("/dev/net/tun", O_RDWR);
    if (fd < 0) {
        perror("open /dev/net/tun");
        return -1;
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    if (dev && *dev) strncpy(ifr.ifr_name, dev, IFNAMSIZ);

    if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
        perror("TUNSETIFF");
        close(fd);
        return -1;
    }
    // return fd; dev name is set in ifr.ifr_name if needed
    return fd;
}

int main(int argc, char* argv[])
{
    char* tapname = "tapB";
    char src_mac[6];
    char dst_mac[6];

    if (parse_mac(argv[1], src_mac) < 0) { 
        fprintf(stderr, "bad src mac = %s\n", argv[1]); 
        return -1; 
    }
    if (parse_mac(argv[2], dst_mac) < 0) { 
        fprintf(stderr, "bad dst mac = %s\n", argv[2]); 
        return -1; 
    }

    int tapfd = tun_alloc(tapname);
    if (tapfd < 0) {
        fprintf(stderr, "Failed to create/open tap %s\n", tapname);
        return -1;
    }

    uint8_t sndbuf[1024];
    uint8_t rcvbuf[1024];

    memcpy(sndbuf, dst_mac, 6);
    memcpy(sndbuf + 6, src_mac, 6);
    sndbuf[12] = 0x08;
    sndbuf[13] = 0x00;

    memset(sndbuf + 14, 49, 60);

    for(int i = 0;i < 14;i++) {
        printf("%x ", sndbuf[i]);
    }
    printf("\n");

    // 注意最小帧64字节 4字节是硬件完成的FCS校验

    ssize_t w = write(tapfd, sndbuf, 74);
    if(w <= 0) {
        fprintf(stderr, "w < 0\n");
        return -1;
    }

    usleep(1000 * 1000 * 10);
    close(tapfd);

    return 0;
}

sudo ip netns exec nsB bridge link set dev tapB learning on